#include <arm_neon.h>
#include <stdlib.h>
#include <iostream>
#include <sys/time.h>
#include <time.h>
using namespace std;

void chuan(int n, int m, int* a, int** matr)
{
    int i, j;
    for (i = 0; i < n; i++)
    {
        int b = i / 32;
        int s = i % 32;
        if (a[b] >> (31 - s) != 0)
        {
            if (matr[n - 1 - i][b] >> (31 - s) == 0)
            {
                for (j = 0; j < m; j++)
                    matr[n - 1 - i][j] = a[j];
                return;
            }
            else
            {
                for (j = 0; j < m; j++)
                    a[j] ^= matr[n - 1 - i][j];
            }
        }
    }
}

void bing(int n, int m, int* a, int** matr)
{
    int i, j, k;
    for (i = 0; i < n; i++)
    {
        int b = i / 32;
        int s = i % 32;
        if (a[b] >> (31 - s) != 0)
        {
            if (matr[n - 1 - i][b] >> (31 - s) == 0)
            {
                for (j = 0; j <= m - 4; j += 4)
                {
                    int32x4_t temp = vld1q_s32(a + j);
                    vst1q_s32(matr[n - 1 - i] + j, temp);
                }
                for (j; j < m; j++)
                    matr[n - 1 - i][j] = a[j];
                return;
            }
            else
            {
                for (j = 0; j <= m - 4; j += 4)
                {
                    int32x4_t t1 = vld1q_s32(matr[n - 1 - i] + j);
                    int32x4_t t2 = vld1q_s32(a + j);
                    t2 = veorq_s32(t1, t2);
                    vst1q_s32(a + j, t2);
                }
                for (j; j < m; j++)
                    a[j] ^= matr[n - 1 - i][j];
            }
        }
    }
}

int shuru(int* a, int n, int m)
{
    for (int j = 0; j < m; j++) a[j] = 0;
    int q = (rand() % n) / 2;
    while (q == 0) q = (rand() % n) / 2;
    int p = n;
    int temp;
    for (int i = 0; i < q; i++)
    {
        if (p != 0)
        {
            p = rand() % p;
            if (i == 0)
                temp = p;
        }
        int bpos = p / 32, spos = p % 32;
        bpos = m - 1 - bpos;
        int ans = 1;
        ans = ans << spos;
        a[bpos] |= ans;
    }
    return temp;
}
int main()
{
    int n, m, u, l;
    srand(time(0));
    n = 20;
    while (n <= 10000)
    {
        u = rand() % (n / 2);
        while (u == 0) u = rand() % (n / 2);
        l = rand() % n + n / 2;
        if (n % 32 == 0)
            m = n / 32;
        else
            m = n / 32 + 1;
        int** mc = new int* [n];
        int** mb = (int**)aligned_alloc(32, n * sizeof(int*));
        for (int i = 0; i < n; i++)
        {
            mc[i] = new int[m];
            mb[i] = (int*)aligned_alloc(32, m * sizeof(int));
        }
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++)
            {
                mc[i][j] = 0;
                mb[i][j] = 0;
            }
        for (int i = 0; i < u; i++)
        {
            int* a1 = new int[m];
            int* a2 = (int*)aligned_alloc(32, n * sizeof(int));
            int temp = shuru(a1, n, m);
            for (int j = 0; j < m; j++)
                a2[j] = a1[j];
            for (int j = 0; j < m; j++)
            {
                mc[n - 1 - temp][j] = a1[j];
                mb[n - 1 - temp][j] = a2[j];
            }
        }

        struct timeval tstart, tend;
        double timeUsed1 = 0.0, timeUsed2 = 0.0;

        for (int i = 0; i < l; i++)
        {
            int* a1 = new int[m];
            int* a2 = (int*)aligned_alloc(32, n * sizeof(int));
            int temp = shuru(a1, n, m);
            for (int j = 0; j < m; j++)
                a2[j] = a1[j];

            gettimeofday(&tstart, NULL);
            chuan(n, m, a1, mc);
            gettimeofday(&tend, NULL);
            timeUsed1 += 1000000 * (tend.tv_sec - tstart.tv_sec) + tend.tv_usec - tstart.tv_usec;

            gettimeofday(&tstart, NULL);
            bing(n, m, a2, mb);
            gettimeofday(&tend, NULL);
            timeUsed2 += 1000000 * (tend.tv_sec - tstart.tv_sec) + tend.tv_usec - tstart.tv_usec;
        }
        cout << n << " " << timeUsed1 / timeUsed2 * 100 << "%" << endl;

        if (n < 100) n += 10;
        if (n >= 100 && n < 200) n += 20;
        if (n >= 200 && n < 500) n += 50;
        if (n>=500 && n<1000) n+=100;
        if (n >= 1000 && n < 3000) n += 500;
        if (n >= 3000) n += 1000;
    }
    return 0;
}
